﻿using System;
using Microsoft.SharePoint.Administration;
using System.Runtime.InteropServices;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using System.Configuration;
using System.ServiceModel;
using System.ServiceModel.Configuration;

namespace CodeCounsel.SharePoint.NavigationService
{
    [GuidAttribute("0c1a4b04-90d5-4cef-be3a-f4591b1ac873")]
    public class NavigationApplicationProxy
        : SPIisWebServiceApplicationProxy
    {
        [Persisted]
        SPServiceLoadBalancer _loadBalancer;

        public override string TypeName
        {
            get { return "Navigation Application Proxy (Demo)"; }
        }

        public NavigationApplicationProxy()
        {
        }

        public NavigationApplicationProxy(string name, NavigationServiceProxy serviceProxy, Uri serviceEndpointUri)
            : base(name, serviceProxy, serviceEndpointUri)
        {
            _loadBalancer = new SPRoundRobinServiceLoadBalancer(serviceEndpointUri);
        }

        public override void Provision()
        {
            base.Provision();
            _loadBalancer.Provision();
            Update();
        }

        public override void Unprovision(bool deleteData)
        {
            _loadBalancer.Unprovision();
            base.Unprovision(deleteData);
            Update();
        }

        public string GetNavigationInformation()
        {
            string channelConfigPath = SPUtility.GetGenericSetupPath(
                @"WebClients\CodeCounsel.SharePoint.NavigationService");
            Configuration clientConfig = OpenClientConfiguration(channelConfigPath);
            ChannelFactory<INavigationApplication> factory =
                new ConfigurationChannelFactory<INavigationApplication>(
                    "http", clientConfig, null);
            factory.ConfigureCredentials(SPServiceAuthenticationMode.Claims);

            SPServiceLoadBalancerContext context = _loadBalancer.BeginOperation();
            try
            {
                INavigationApplication channel = factory.CreateChannelActingAsLoggedOnUser<INavigationApplication>(
                    new EndpointAddress(context.EndpointAddress));
                return channel.GetNavigationInformation();
            }
            finally
            {
                context.EndOperation();
            }
        }

        public static NavigationApplicationProxy Create(string name, 
            NavigationServiceProxy applicationProxy, Uri serviceEndpointUri,
            bool addToDefaultGroup)
        {
            NavigationApplicationProxy proxy = new NavigationApplicationProxy(name, applicationProxy, serviceEndpointUri);
            proxy.Update();
            if (addToDefaultGroup)
            {
                SPServiceApplicationProxyGroup group = SPServiceApplicationProxyGroup.Default;
                group.Add(proxy);
                group.Update();
            }
            return proxy;
        }

        public static NavigationApplicationProxy GetProxy(SPServiceContext context)
        {
            return (NavigationApplicationProxy)context.GetDefaultProxy(typeof(NavigationApplicationProxy));
        }
    }
}
